#include "Kernel_PCH.h"
#include "IThread.h"

/*--------------------------------------------------------------------------*/

IThread::IThread(const std::string& name, float frequency, EThread::Type type) :
	m_sdlthread(NULL),
	m_name(name),
	m_frequency(frequency),
	m_mutex(NULL),
	m_synctype(type)
{
	m_cond = SDL_CreateCond();
	m_mutex = SDL_CreateMutex();
}

/*--------------------------------------------------------------------------*/

IThread::~IThread()
{
	if (m_sdlthread)
	{
		Wait(NULL);
	}

	SDL_DestroyCond(m_cond);
	SDL_DestroyMutex(m_mutex);
}

/*--------------------------------------------------------------------------*/

void IThread::StartThread()
{
	__Check(m_sdlthread == NULL);
	
	if (m_sdlthread == NULL)
	{
		g_Kernel->RegisterThread(this);
		m_keepThreadAlive = true;
		__Info("Starting new thread %s", m_name.c_str());
		m_sdlthread = SDL_CreateThread(ThreadFunction, m_name.c_str(), (void*) this);
	}
}

/*--------------------------------------------------------------------------*/

void IThread::StopThread()
{
	__Check(m_sdlthread != NULL);

	if (m_sdlthread)
	{
		g_Kernel->UnregisterThread(this);
		m_keepThreadAlive = false;
	}
}

/*--------------------------------------------------------------------------*/

const std::string& IThread::GetThreadName() const
{
	return m_name;
}

/*--------------------------------------------------------------------------*/

int IThread::ThreadFunc()
{
	int result = 0;

	if (m_keepThreadAlive == false)
	{
		result = 1;
	}
	else
	{
		result = ThreadLoop();	
	}
	
	return result;
}

/*--------------------------------------------------------------------------*/

void IThread::Wait(int* returnValue)
{
	__Check(m_sdlthread);

	if (m_sdlthread)
	{
		SDL_WaitThread(m_sdlthread, returnValue);
	}
}

/*--------------------------------------------------------------------------*/

void IThread::OnThreadStart()
{

}

/*--------------------------------------------------------------------------*/

void IThread::OnThreadStop()
{

}

/*--------------------------------------------------------------------------*/

float IThread::GetFrequency() const
{
	return m_frequency;
}

/*--------------------------------------------------------------------------*/

void IThread::LockCond()
{
	SDL_CondWait(m_cond, m_mutex);
}

/*--------------------------------------------------------------------------*/

void IThread::UnlockCond()
{
	SDL_CondSignal(m_cond);
}

/*--------------------------------------------------------------------------*/

void IThread::LockMutex()
{
	SDL_LockMutex(m_mutex);
}

/*--------------------------------------------------------------------------*/

void IThread::UnlockMutex()
{
	SDL_UnlockMutex(m_mutex);
}

/*--------------------------------------------------------------------------*/

EThread::Type IThread::GetSyncType() const
{
	return m_synctype;
}

/*--------------------------------------------------------------------------*/

int ThreadFunction( void* data )
{
	IThread* thread = (IThread*) data;
	int result = 0;

	thread->OnThreadStart();
	
	while (result == 0)
	{
		result = thread->ThreadFunc();
		g_Kernel->LockThread(thread);
	}

	thread->OnThreadStop();
	SDL_cond;
	return 0;
}

/*--------------------------------------------------------------------------*/